<?php

namespace App\Services\Utils;

use BaiduBce\Services\Bos\BosClient;
use Illuminate\Http\UploadedFile;
use ZeonWang\BaiduBosClient\BosInterface;
use ZeonWang\BaiduBosClient\Facades\Bos;

trait Bosable
{
    protected $default_key_prefix = 'misc/';

    /**
     * @param UploadedFile $file
     * @param string $bos_key_prefix
     * @param bool $hash_key
     * @param string $custom_ext
     * @return string
     */
    public function uploadPostFile(UploadedFile $file, $bos_key_prefix = '', $hash_key = true, $custom_ext = '')
    {
        $file_origin_name = $file->getClientOriginalName();
        $prefix = $bos_key_prefix ?: $this->default_key_prefix;

        if ($hash_key) {
            $time_stamp = date('_Y_m_d');
            $ext = $custom_ext ?: last(explode(".", $file_origin_name));
            $hash = md5($file_origin_name . time());
            $bos_key = $prefix . $hash . $time_stamp . '.' . $ext;
        } else {
            $bos_key = $prefix . $file_origin_name;
        }

        /** @var BosClient $client */
        $client = Bos::client();

        $client->putObjectFromFile(Bos::bucket(), $bos_key, $file->getRealPath());

        return $bos_key;
    }

    /**
     * @param string $file_path
     * @param string $bos_key_prefix
     * @param bool $hash_key
     * @return string
     */
    public function uploadFile($file_path, $bos_key_prefix = '', $hash_key = true)
    {
        $prefix = $bos_key_prefix ?: $this->default_key_prefix;

        if ($hash_key) {
            $time_stamp = '_' . date('Y_m_d');
            $ext = pathinfo($file_path, PATHINFO_EXTENSION);
            $hash = md5($file_path . time());
            $bos_key = $prefix . $hash . $time_stamp . '.' . $ext;
        } else {
            $bos_key = $prefix . $file_path;
        }

        $bos = app(BosInterface::class);

        $bos->client->putObjectFromFile($bos->bucket, $bos_key, $file_path);

        return $bos_key;
    }

    /**
     * @param $key
     * @return mixed
     */
    public function getStaticUrl($key)
    {
        return head(explode('?', $this->getBosUrl($key)));
    }

    /**
     * @param string $bos_key
     * @return mixed
     */
    public function getBosUrl($bos_key)
    {
        if (mb_strpos($bos_key, 'http') === 0) return $bos_key;

        $file_url = Bos::client()
            ->generatePreSignedUrl(Bos::bucket(), $bos_key, Bos::sign_array());

        return $file_url;
    }

    /**
     * @param array $column_names
     * @throws \Exception
     */
    public function deleteBosColumns(array $column_names)
    {
        if (! is_array($column_names)) {
            throw new \Exception('column_names need to be an array');
        }

        array_map([$this, 'deleteBosColumn'], $column_names);
    }

    /**
     * @param array $column_names
     * @throws \Exception
     */
    public function deleteBosJsonColumns(array $column_names)
    {
        if (! is_array($column_names)) {
            throw new \Exception('column_names need to be an array');
        }

        array_map([$this, 'deleteBosJsonArr'], $column_names);
    }

    /**
     * @param string $column_name
     * @return bool|null|string
     * @throws \Exception
     */
    public function deleteBosColumn($column_name)
    {
        if (! $column_name || ! is_string($column_name)) {
            throw new \Exception('column_name need to be an column name');
        }

        if (! isset($this->attributes) || ! $this->attributes[$column_name]) return null;

        return $this->deleteBosKey($this->attributes[$column_name]);
    }

    /**
     * @param $key
     * @return bool
     */
    public function deleteBosKey($key)
    {
        if (! $this->isBosKeyValidated($key)) return false;

        /** @var BosClient $client */
        $client = Bos::client();
        try {
            $client->deleteObject(Bos::bucket(), $key);logger($key);
        } catch (\Exception $e) {
            logger("[BOS ERROR] bos key: {$key} delete error: {$e->getMessage()}");
            return false;
        }

        return true;
    }

    /**
     * @param $column_name
     * @return bool|null
     * @throws \Exception
     */
    public function deleteBosJsonArr($column_name)
    {
        if (! $column_name || ! is_string($column_name)) {
            throw new \Exception('column_name need to be an column name');
        }

        if (! isset($this->attributes) || ! $this->attributes[$column_name]) return null;

        $bos_key_arr = json_decode($this->attributes[$column_name]);

        if (! is_array($bos_key_arr) || ! count($bos_key_arr)) {
            return false;
        } else {
            array_map([$this, 'deleteBosKey'], $bos_key_arr);

            return true;
        }
    }

    /**
     * @param mixed $key
     * @return bool
     */
    private function isBosKeyValidated($key)
    {
        return $key && is_string($key) && mb_strpos($key, 'http') !== 0;
    }

}
